﻿using System;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.Serialization;
using UnityEngine.UI;

namespace IQIGame.Onigao.Framework
{
    public class ExToggle : Toggle, IUGUIEx
    {
        #region override listener

        // 自定义的 UnityEvent 只允许一个侦听器
        [System.Serializable]
        public class SingleListenerUnityEvent : ToggleEvent
        {
            private UnityAction<bool> baseListener;
            private UnityAction<bool> currentListener;

            public SingleListenerUnityEvent(UnityAction<bool> call)
            {
                baseListener = call;
                base.AddListener(call);
            }

            public new void AddListener(UnityAction<bool> call)
            {
                if (call == null)
                    return;

                // 如果已经存在侦听器，则阻止添加
                if (currentListener != null)
                {
                    LogGame.LogError("ExToggle: 不能添加多个侦听器。");
                    return;
                }

                base.RemoveAllListeners();
                base.AddListener(call);
                base.AddListener(baseListener);
                currentListener = call;
            }

            public new void RemoveListener(UnityAction<bool> call)
            {
                base.RemoveListener(call);
                if (currentListener == call)
                {
                    currentListener = null;
                }
            }

            public new void RemoveAllListeners()
            {
                base.RemoveAllListeners();
                currentListener = null;
                baseListener = null;
            }
        }

        [SerializeField] private SingleListenerUnityEvent _onValueChanged;

        public new SingleListenerUnityEvent onValueChanged
        {
            get { return _onValueChanged; }
            set
            {
                _onValueChanged = value;
                base.onValueChanged = _onValueChanged;
            }
        }

        #endregion

        protected ExToggle() : base()
        {
            this.onValueChanged = new SingleListenerUnityEvent(this.OnValChged);
        }

        public object dynamicData { get; set; }

        public void SetActive(bool isActive)
        {
            this.gameObject.SetActive(isActive);
        }

        private Action<ExToggle> _systemCallValChged;

        public Action<ExToggle> systemCallValChged
        {
            get => _systemCallValChged;
            set => _systemCallValChged = value;
        }

        private Func<GameObject, bool> _funcCheckIsCanClick;

        public Func<GameObject, bool> funcCheckIsCanClick
        {
            get => _funcCheckIsCanClick;
            set => _funcCheckIsCanClick = value;
        }


        private void OnValChged(bool isOn)
        {
            this.ChangeViewState(isOn);
            this.systemCallValChged?.Invoke(this);
        }

        [FormerlySerializedAs("_gobjSelected")]
        [SerializeField] private GameObject _gobjOn;
        [SerializeField] private GameObject _gobjOff;

        private void ChangeViewState(bool isActive)
        {
            if (this._gobjOn)
                this._gobjOn.SetActive(isActive);

            if (this._gobjOff)
                this._gobjOff.SetActive(!isActive);
        }

        public override void OnPointerClick(PointerEventData eventData)
        {
            if (CheckIsCanClick())
                base.OnPointerClick(eventData);
        }

        private bool CheckIsCanClick()
        {
            return funcCheckIsCanClick == null || funcCheckIsCanClick(this.gameObject);
        }

        public override void OnSubmit(BaseEventData eventData)
        {
            if (CheckIsCanClick())
                base.OnSubmit(eventData);
        }
    }
}
